home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / JSplitPane.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  31.3 KB  |  976 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)JSplitPane.java    1.47 98/08/28
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package javax.swing;
  16.  
  17. import java.awt.*;
  18. import javax.swing.border.Border;
  19. import javax.swing.plaf.*;
  20. import javax.accessibility.*;
  21.  
  22. import java.io.ObjectOutputStream;
  23. import java.io.ObjectInputStream;
  24. import java.io.IOException;
  25.  
  26.  
  27. /**
  28.  * JSplitPane is used to divide two (and only two) Components. The two
  29.  * Components are graphically divided based on the look and feel
  30.  * implementation, and the two Components can then be interactively 
  31.  * resized by the user.
  32.  * <p>
  33.  * The two Components can be aligned left to right using
  34.  * <code>JSplitPane.HORIZONTAL_SPLIT</code>, or top to bottom using 
  35.  * <code>JSplitPane.VERTICAL_SPLIT</code>.
  36.  * The preferred way to change the size of the Components is to invoke
  37.  * <code>setDividerLocation</code> where <code>location</code> is either
  38.  * the new x or y position, depending on the orientation of the
  39.  * JSplitPane. If one component changes, JSplitPane also attempts to 
  40.  * reposition the other component.
  41.  * <p>
  42.  * To resize the Components to their preferred sizes invoke
  43.  * <code>resetToPreferredSizes</code>.
  44.  * <p>
  45.  * When the user is resizing the Components the minimum size of the
  46.  * Components is used to determine the maximum/minimum position the
  47.  * Components can be set to. So that if the minimum size of the two
  48.  * components is greater than the size of the splitpane the divider
  49.  * will not allow you to resize it. To alter the minimum size of a
  50.  * JComponent, see {@link JComponent#setMinimumSize}.
  51.  * <p>
  52.  * For the keyboard keys used by this component in the standard Look and
  53.  * Feel (L&F) renditions, see the
  54.  * <a href="doc-files/Key-Index.html#JSplitPane">JSplitPane</a> key assignments.
  55.  * <p>
  56.  * <strong>Warning:</strong>
  57.  * Serialized objects of this class will not be compatible with
  58.  * future Swing releases.  The current serialization support is appropriate
  59.  * for short term storage or RMI between applications running the same
  60.  * version of Swing.  A future release of Swing will provide support for
  61.  * long term persistence.
  62.  *
  63.  * @see #setDividerLocation
  64.  * @see #resetToPreferredSizes
  65.  *
  66.  * @version 1.47 08/28/98
  67.  * @author Scott Violet
  68.  */
  69. public class JSplitPane extends JComponent implements Accessible
  70. {
  71.     /**
  72.      * @see #getUIClassID
  73.      * @see #readObject
  74.      */
  75.     private static final String uiClassID = "SplitPaneUI";
  76.  
  77.     /**
  78.      * Vertical split indicates the Components are split along the
  79.      * y axis, eg the two Components will be split one on top of the other.
  80.      */
  81.     public final static int VERTICAL_SPLIT = 0;
  82.  
  83.     /**
  84.      * Horizontal split indicates the Components are split along the
  85.      * x axis, eg the two Components will be split one to the left of the
  86.      * other.
  87.      */
  88.     public final static int HORIZONTAL_SPLIT = 1;
  89.  
  90.     /**
  91.      * Used to add a Component to the left of the other Component.
  92.      */
  93.     public final static String LEFT = "left";
  94.  
  95.     /**
  96.      * Used to add a Component to the right of the other Component.
  97.      */
  98.     public final static String RIGHT = "right";
  99.  
  100.     /**
  101.      * Used to add a Component above the other Component.
  102.      */
  103.     public final static String TOP = "top";
  104.  
  105.     /**
  106.      * Used to add a Component below the other Component.
  107.      */
  108.     public final static String BOTTOM = "bottom";
  109.  
  110.     /**
  111.      * Used to add a Component that will represent the divider.
  112.      */
  113.     public final static String DIVIDER = "divider";
  114.  
  115.     /**
  116.      * Bound property name for orientation (horizontal or vertical).
  117.      */
  118.     public final static String ORIENTATION_PROPERTY = "orientation";
  119.  
  120.     /**
  121.      * Bound property name for continuousLayout.
  122.      */
  123.     public final static String CONTINUOUS_LAYOUT_PROPERTY = "continuousLayout";
  124.  
  125.     /**
  126.      * Bound property name for border.
  127.      */
  128.     public final static String DIVIDER_SIZE_PROPERTY = "dividerSize";
  129.  
  130.     /**
  131.      * Bound property for oneTouchExpandable.
  132.      */
  133.     public final static String ONE_TOUCH_EXPANDABLE_PROPERTY = 
  134.                                "oneTouchExpandable";
  135.  
  136.     /**
  137.      * Bound property for lastLocation.
  138.      */
  139.     public final static String LAST_DIVIDER_LOCATION_PROPERTY =
  140.                                "lastDividerLocation";
  141.  
  142.     /**
  143.      * How the views are split.
  144.      */
  145.     protected int orientation;
  146.  
  147.     /**
  148.      * Whether or not the views are continuously redisplayed while
  149.      * resizing.
  150.      */
  151.     protected boolean continuousLayout;
  152.  
  153.     /**
  154.      * The left or top component.
  155.      */
  156.     protected Component leftComponent;
  157.  
  158.     /**
  159.      * The right or bottom component.
  160.      */
  161.     protected Component rightComponent;
  162.  
  163.     /**
  164.      * Size of the divider.
  165.      */
  166.     protected int dividerSize;
  167.  
  168.     /**
  169.      * Is a little widget provided to quickly expand/collapse the
  170.      * split pane?
  171.      */
  172.     protected boolean oneTouchExpandable;
  173.  
  174.     /**
  175.      * Previous location of the split pane.
  176.      */
  177.     protected int lastDividerLocation;
  178.  
  179.     /**
  180.      * Returns a new JSplitPane configured to arrange the child
  181.      * components side-by-side horizontally with no continuous 
  182.      * layout, using two buttons for the compoents.
  183.      */
  184.     public JSplitPane() {
  185.         this(JSplitPane.HORIZONTAL_SPLIT, false, new JButton("left button"),
  186.              new JButton("right button"));
  187.     }
  188.  
  189.     /**
  190.      * Returns a new JSplitPane configured with the specified orientation
  191.      * and no continuous layout.
  192.      *
  193.      * @param newOrientation an int specifying the horizontal or vertical
  194.      *        orientation
  195.      */
  196.     public JSplitPane(int newOrientation) {
  197.         this(newOrientation, false);
  198.     }
  199.  
  200.     /**
  201.      * Returns a new JSplitPane with the specified orientation and
  202.      * redrawing style.
  203.      *
  204.      * @param newOrientation an int specifying the horizontal or vertical
  205.      *        orientation
  206.      * @param newContinuousLayout  a boolean, true for the components to 
  207.      *        redraw continuously as the divider changes position, false
  208.      *        to wait until the divider position stops changing to redraw
  209.      */
  210.     public JSplitPane(int newOrientation, boolean newContinuousLayout) {
  211.         this(newOrientation, newContinuousLayout, null, null);
  212.     }
  213.  
  214.     /**
  215.      * Returns a new JSplitPane with the specified orientation and
  216.      * with the specifiied components that does not do continuous
  217.      * redrawing.
  218.      *
  219.      * @param newOrientation an int specifying the horizontal or vertical
  220.      *        orientation
  221.      * @param newContinuousLayout  a boolean, true for the components to 
  222.      *        redraw continuously as the divider changes position, false
  223.      *        to wait until the divider position stops changing to redraw
  224.      * @param newLeftComponent the Component that will appear on the left
  225.      *        of a horizontally-split pane, or at the top of a
  226.      *        vertically-split pane.
  227.      */
  228.     public JSplitPane(int newOrientation,
  229.                       Component newLeftComponent, Component newRightComponent){
  230.         this(newOrientation, false, newLeftComponent, newRightComponent);
  231.     }
  232.  
  233.     /**
  234.      * Returns a new JSplitPane with the specified orientation and
  235.      * redrawing style, and with the specifiied components.
  236.      *
  237.      * @param newOrientation an int specifying the horizontal or vertical
  238.      *        orientation
  239.      * @param newContinuousLayout  a boolean, true for the components to 
  240.      *        redraw continuously as the divider changes position, false
  241.      *        to wait until the divider position stops changing to redraw
  242.      * @param newLeftComponent the Component that will appear on the left
  243.      *        of a horizontally-split pane, or at the top of a
  244.      *        vertically-split pane.
  245.      */
  246.     public JSplitPane(int newOrientation, boolean newContinuousLayout,
  247.                       Component newLeftComponent, Component newRightComponent){
  248.         super();
  249.  
  250.         setLayout(null);
  251.         orientation = newOrientation;
  252.         if (orientation != HORIZONTAL_SPLIT && orientation != VERTICAL_SPLIT)
  253.             throw new IllegalArgumentException("cannot create JSplitPane, " +
  254.                                                "orientation must be one of " +
  255.                                                "JSplitPane.HORIZONTAL_SPLIT " +
  256.                                                "or JSplitPane.VERTICAL_SPLIT");
  257.         continuousLayout = newContinuousLayout;
  258.         if (newLeftComponent != null)
  259.             setLeftComponent(newLeftComponent);
  260.         if (newRightComponent != null)
  261.             setRightComponent(newRightComponent);
  262.         updateUI();
  263.  
  264.     }
  265.  
  266.     /**
  267.      * Sets the L&F object that renders this component.
  268.      *
  269.      * @param ui  the SplitPaneUI L&F object
  270.      * @see UIDefaults#getUI
  271.      */
  272.     public void setUI(SplitPaneUI ui) {
  273.         if ((SplitPaneUI)this.ui != ui) {
  274.             super.setUI(ui);
  275.             revalidate();
  276.         }
  277.     }
  278.  
  279.     /**
  280.      * Returns the SplitPaneUI that is providing the current look and 
  281.      * feel. 
  282.      *
  283.      * @return the SplitPaneUI object that renders this component
  284.      * @beaninfo
  285.      *       expert: true
  286.      *  description: The L&F object that renders this component.
  287.      */
  288.     public SplitPaneUI getUI() {
  289.         return (SplitPaneUI)ui;
  290.     }
  291.  
  292.     /**
  293.      * Notification from the UIManager that the L&F has changed. 
  294.      * Replaces the current UI object with the latest version from the 
  295.      * UIManager.
  296.      *
  297.      * @see JComponent#updateUI
  298.      */
  299.     public void updateUI() {
  300.         setUI((SplitPaneUI)UIManager.getUI(this));
  301.         revalidate();
  302.     }
  303.  
  304.     /**
  305.      * Returns the name of the L&F class that renders this component.
  306.      *
  307.      * @return "SplitPaneUI"
  308.      * @see JComponent#getUIClassID
  309.      * @see UIDefaults#getUI
  310.      * @beaninfo
  311.      *       expert: true
  312.      *  description: A string that specifies the name of the L&F class.
  313.      */
  314.     public String getUIClassID() {
  315.         return uiClassID;
  316.     }
  317.  
  318.     /**
  319.      * Sets the size of the divider.
  320.      *
  321.      * @param newSize an int giving the size of the divider in pixels
  322.      * @beaninfo
  323.      *        bound: true
  324.      *  description: The size of the divider.
  325.      */
  326.     public void setDividerSize(int newSize) {
  327.         int           oldSize = dividerSize;
  328.  
  329.         if (oldSize != newSize) {
  330.             dividerSize = newSize;
  331.             firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, newSize);
  332.         }
  333.     }
  334.  
  335.     /**
  336.      * Returns the size of the divider.
  337.      *
  338.      * @return an int giving the size of the divider in pixels
  339.      */
  340.     public int getDividerSize() {
  341.         return dividerSize;
  342.     }
  343.  
  344.     /**
  345.      * Sets the component to the left (or above) the divider.
  346.      *
  347.      * @param comp the Component to display in that position
  348.      */
  349.     public void setLeftComponent(Component comp) {
  350.         if (comp == null) {
  351.             if (leftComponent != null) {
  352.                 remove(leftComponent);
  353.                 leftComponent = null;
  354.             }
  355.         } else {
  356.             add(comp, JSplitPane.LEFT);
  357.         }
  358.     }
  359.  
  360.     /**
  361.      * Returns the component to the left (or above) the divider.
  362.      *
  363.      * @return the Component displayed in that position
  364.      * @beaninfo
  365.      *    preferred: true
  366.      *  description: The component to the left (or above) the divider.
  367.      */
  368.     public Component getLeftComponent() {
  369.         return leftComponent;
  370.     }
  371.  
  372.     /**
  373.      * Sets the component above, or to the left of the divider.
  374.      *
  375.      * @param comp the Component to display in that position
  376.      * @beaninfo
  377.      *  description: The component above, or to the left of the divider.
  378.      */
  379.     public void setTopComponent(Component comp) {
  380.         setLeftComponent(comp);
  381.     }
  382.  
  383.     /**
  384.      * Returns the component above, or to the left of the divider.
  385.      *
  386.      * @return the Component displayed in that position
  387.      */
  388.     public Component getTopComponent() {
  389.         return leftComponent;
  390.     }
  391.  
  392.     /**
  393.      * Sets the component to the right (or below) the divider.
  394.      *
  395.      * @param comp the Component to display in that position
  396.      * @beaninfo
  397.      *    preferred: true
  398.      *  description: The component to the right (or below) the divider.
  399.      */
  400.     public void setRightComponent(Component comp) {
  401.         if (comp == null) {
  402.             if (rightComponent != null) {
  403.                 remove(rightComponent);
  404.                 rightComponent = null;
  405.             }
  406.         } else {
  407.             add(comp, JSplitPane.RIGHT);
  408.         }
  409.     }
  410.  
  411.     /**
  412.      * Returns the component to the right (or below) the divider.
  413.      *
  414.      * @return the Component displayed in that position
  415.      */
  416.     public Component getRightComponent() {
  417.         return rightComponent;
  418.     }
  419.  
  420.     /**
  421.      * Sets the component below, or to the right of the divider.
  422.      *
  423.      * @param comp the Component to display in that position
  424.      * @beaninfo
  425.      *  description: The component below, or to the right of the divider.
  426.      */
  427.     public void setBottomComponent(Component comp) {
  428.         setRightComponent(comp);
  429.     }
  430.  
  431.     /**
  432.      * Returns the component below, or to the right of the divider.
  433.      *
  434.      * @return the Component displayed in that position
  435.      */
  436.     public Component getBottomComponent() {
  437.         return rightComponent;
  438.     }
  439.  
  440.     /**
  441.      * Determines whether the JSplitPane provides a UI widget
  442.      * on the divider to quickly expand/collapse the divider.
  443.      *
  444.      * @param newValue a boolean, where true means to provide a
  445.      *        collapse/expand widget
  446.      * @beaninfo
  447.      *        bound: true
  448.      *  description: UI widget on the divider to quickly 
  449.      *               expand/collapse the divider.
  450.      */
  451.     public void setOneTouchExpandable(boolean newValue) {
  452.         boolean           oldValue = oneTouchExpandable;
  453.  
  454.         oneTouchExpandable = newValue;
  455.         firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue, newValue);
  456.         repaint();
  457.     }
  458.  
  459.     /**
  460.      * Returns true if the pane provides a UI widget to collapse/expand
  461.      * the divider.
  462.      *
  463.      * @return true if the split pane provides a collapse/expand widget
  464.      */
  465.     public boolean isOneTouchExpandable() {
  466.         return oneTouchExpandable;
  467.     }
  468.  
  469.     /**
  470.      * Sets the last location the divider was at to
  471.      * <code>newLastLocation</code>.
  472.      *
  473.      * @param newLastLocation an int specifying the last divider location
  474.      *        in pixels, from the left (or upper) edge of the pane to the 
  475.      *        left (or upper) edge of the divider
  476.      * @beaninfo
  477.      *        bound: true
  478.      *  description: The last location the divider was at.
  479.      */
  480.     public void setLastDividerLocation(int newLastLocation) {
  481.         int               oldLocation = lastDividerLocation;
  482.  
  483.         lastDividerLocation = newLastLocation;
  484.         firePropertyChange(LAST_DIVIDER_LOCATION_PROPERTY, oldLocation,
  485.                            newLastLocation);
  486.     }
  487.     
  488.     /**
  489.      * Returns the last location the divider was at.
  490.      *
  491.      * @return an int specifying the last divider location as a count
  492.      *       of pixels from the left (or upper) edge of the pane to the 
  493.      *       left (or upper) edge of the divider
  494.      */
  495.     public int getLastDividerLocation() {
  496.         return lastDividerLocation;
  497.     }
  498.  
  499.     /**
  500.      * Sets the orientation, or how the splitter is divided. The options
  501.      * are:<ul>
  502.      * <li>JSplitPane.VERTICAL_SPLIT  (above/below orientation of components)
  503.      * <li>JSplitPane.HORIZONTAL_SPLIT  (left/right orientation of components)
  504.      * </ul>
  505.      *
  506.      * @param orientation an int specifying the orientation
  507.      * @beaninfo
  508.      *        bound: true
  509.      *  description: The orientation, or how the splitter is divided.
  510.      */
  511.     public void setOrientation(int orientation) {
  512.         if (orientation != VERTICAL_SPLIT && orientation != HORIZONTAL_SPLIT) {
  513.            throw new IllegalArgumentException("JSplitPane: orientation must " +
  514.                                               "be one of " +
  515.                                               "JSplitPane.VERTICAL_SPLIT or " +
  516.                                               "JSplitPane.HORIZONTAL_SPLIT");
  517.         }
  518.  
  519.         int           oldOrientation = this.orientation;
  520.  
  521.         this.orientation = orientation;
  522.         firePropertyChange(ORIENTATION_PROPERTY, oldOrientation, orientation);
  523.     }
  524.  
  525.     /**
  526.      * Returns the orientation.
  527.      * 
  528.      * @return an int giving the orientation
  529.      * @see #setOrientation
  530.      */
  531.     public int getOrientation() {
  532.         return orientation;
  533.     }
  534.  
  535.     /**
  536.      * Sets whether or not the child components are continuously
  537.      * redisplayed and layed out during user intervention.
  538.      *
  539.      * @param newContinuousLayout  a boolean, true if the components
  540.      *        are continuously redrawn as the divider changes position
  541.      * @beaninfo
  542.      *        bound: true
  543.      *  description: Whether or not the child components are
  544.      *               continuously redisplayed and layed out during
  545.      *               user intervention.
  546.      */
  547.     public void setContinuousLayout(boolean newContinuousLayout) {
  548.         boolean           oldCD = continuousLayout;
  549.  
  550.         continuousLayout = newContinuousLayout;
  551.         firePropertyChange(CONTINUOUS_LAYOUT_PROPERTY, oldCD,
  552.                            newContinuousLayout);
  553.     }
  554.  
  555.     /**
  556.      * Returns true if the child comopnents are continuously redisplayed and
  557.      * layed out during user intervention.
  558.      *
  559.      * @return true if the components are continuously redrawn as the
  560.      *         divider changes position
  561.      */
  562.     public boolean isContinuousLayout() {
  563.         return continuousLayout;
  564.     }
  565.  
  566.     /**
  567.      * Messaged to relayout the JSplitPane based on the preferred size
  568.      * of the children components.
  569.      */
  570.     public void resetToPreferredSizes() {
  571.         SplitPaneUI         ui = getUI();
  572.  
  573.         if (ui != null) {
  574.             ui.resetToPreferredSizes(this);
  575.         }
  576.     }
  577.  
  578.     /**
  579.      * Sets the divider location as a percentage of the JSplitPane's size.
  580.      *
  581.      * @param proportionalLocation  a double-precision floating point value
  582.      *        that specifies a percentage, from zero (top/left) to 1.0
  583.      *        (bottom/right)
  584.      * @exception IllegalArgumentException if the specified location is < 0
  585.      *            or > 1.0
  586.      * @beaninfo
  587.      *  description: The location of the divider.
  588.      */
  589.     public void setDividerLocation(double proportionalLocation) {
  590.         if (proportionalLocation < 0.0 || 
  591.            proportionalLocation > 1.0) {
  592.             throw new IllegalArgumentException("proportional location must " +
  593.                                                "be between 0.0 and 1.0.");
  594.         }
  595.         if (getOrientation() == VERTICAL_SPLIT) {
  596.             setDividerLocation((int)((double)(getHeight() - getDividerSize()) *
  597.                                      proportionalLocation));
  598.         } else {
  599.             setDividerLocation((int)((double)(getWidth() - getDividerSize()) *
  600.                                      proportionalLocation));
  601.         }
  602.     }
  603.  
  604.     /**
  605.      * Sets the location of the divider. This is passed off to the 
  606.      * look and feel implementation.
  607.      *
  608.      * @param location an int specifying a UI-specific value (typically a 
  609.      *        pixel count)
  610.      */
  611.     public void setDividerLocation(int location) {
  612.         SplitPaneUI         ui = getUI();
  613.  
  614.         if (ui != null) {
  615.             ui.setDividerLocation(this, location);
  616.         }
  617.     }
  618.  
  619.     /**
  620.      * Returns the location of the divider from the look and feel
  621.      * implementation.
  622.      *
  623.      * @return an int specifying a UI-specific value (typically a 
  624.      *         pixel count)
  625.      */
  626.     public int getDividerLocation() {
  627.         SplitPaneUI         ui = getUI();
  628.  
  629.         if (ui != null) {
  630.             return ui.getDividerLocation(this);
  631.         }
  632.         return -1;
  633.     }
  634.  
  635.     /**
  636.      * Returns the minimum location of the divider from the look and feel
  637.      * implementation.
  638.      *
  639.      * @return an int specifying a UI-specific value for the minimum
  640.      *         location (typically a pixel count)
  641.      * @beaninfo
  642.      *  description: The minimum location of the divider from the L&F.
  643.      */
  644.     public int getMinimumDividerLocation() {
  645.         SplitPaneUI         ui = getUI();
  646.  
  647.         if (ui != null) {
  648.             return ui.getMinimumDividerLocation(this);
  649.         }
  650.         return -1;
  651.     }
  652.  
  653.     /**
  654.      * Returns the maximum location of the divider from the look and feel
  655.      * implementation.
  656.      *
  657.      * @return an int specifying a UI-specific value for the maximum
  658.      *         location (typically a pixel count)
  659.      */
  660.     public int getMaximumDividerLocation() {
  661.         SplitPaneUI         ui = getUI();
  662.  
  663.         if (ui != null) {
  664.             return ui.getMaximumDividerLocation(this);
  665.         }
  666.         return -1;
  667.     }
  668.  
  669.     /**
  670.      * Removes the child component, <code>component</code> from the
  671.      * pane. Resets the leftComponent or rightComponent instance
  672.      * variable, as necessary.
  673.      * 
  674.      * @param component the Component to remove
  675.      */
  676.     public void remove(Component component) {
  677.         if (component == leftComponent) {
  678.             leftComponent = null;
  679.         } else if (component == rightComponent) {
  680.             rightComponent = null;
  681.         }
  682.         super.remove(component);
  683.  
  684.         // Update the JSplitPane on the screen
  685.         revalidate();
  686.         repaint();
  687.     }
  688.  
  689.     /**
  690.      * Removes the Component at the specified index. Updates the
  691.      * leftComponent and rightComponent instance variables
  692.      * as necessary, and then messages super.
  693.      *
  694.      * @param index an int specifying the component to remove, where
  695.      *        1 specifies the left/top component and 2 specifies the 
  696.      *        bottom/right component
  697.      */
  698.     public void remove(int index) {
  699.         Component    comp = getComponent(index);
  700.  
  701.         if (comp == leftComponent) {
  702.             leftComponent = null;
  703.         } else if (comp == rightComponent) {
  704.             rightComponent = null;
  705.         }
  706.         super.remove(index);
  707.  
  708.         // Update the JSplitPane on the screen
  709.         revalidate();
  710.         repaint();
  711.     }
  712.  
  713.     /**
  714.      * Removes all the child components from the receiver. Resets the
  715.      * leftComonent and rightComponent instance variables.
  716.      */
  717.     public void removeAll() {
  718.         leftComponent = rightComponent = null;
  719.         super.removeAll();
  720.  
  721.         // Update the JSplitPane on the screen
  722.         revalidate();
  723.         repaint();
  724.     }
  725.  
  726.     /**
  727.      * If <code>constraints</code> identifies the left/top or
  728.      * right/bottom child component, and a component with that identifier
  729.      * was previously added, it will be removed and then <code>comp</code>
  730.      * will be added in its place. If <code>constraints</code> is not
  731.      * one of the known identifers the layout manager may throw an
  732.      * IllegalArgumentException.
  733.      * <p>
  734.      * The possible constraints objects (Strings) are:<ul>
  735.      * <li>JSplitPane.TOP
  736.      * <li>JSplitPane.LEFT
  737.      * <li>JSplitPane.BOTTOM
  738.      * <li>JSplitPane.RIGHT
  739.      * </ul>
  740.      * If the constraints object is null, the component is added in the
  741.      * first available position (left/top if open, else right/bottom).
  742.      * 
  743.      * @param comp        the component to add
  744.      * @param constraints an Object specifying the layout constraints 
  745.      *                    (position) for this component
  746.      * @param index       an int specifying the index in the container's
  747.      *                    list.
  748.      * @exception IllegalArgumentException thrown if the constraints object
  749.      *            does not match an existing component
  750.      * @see java.awt.Container#addImpl(Component, Object, int)
  751.      */
  752.     protected void addImpl(Component comp, Object constraints, int index) 
  753.     {
  754.         Component             toRemove;
  755.  
  756.         if (constraints != null && !(constraints instanceof String)) {
  757.             throw new IllegalArgumentException("cannot add to layout: " +
  758.                                                "constraint must be a string " +
  759.                                                "(or null)");
  760.         }
  761.  
  762.         /* If the constraints are null and the left/right component is
  763.            invalid, add it at the left/right component. */
  764.         if (constraints == null) {
  765.             if (getLeftComponent() == null) {
  766.                 constraints = JSplitPane.LEFT;
  767.             } else if (getRightComponent() == null) {
  768.                 constraints = JSplitPane.RIGHT;
  769.             }
  770.         }
  771.             
  772.         /* Find the Component that already exists and remove it. */
  773.         if (constraints != null && (constraints.equals(JSplitPane.LEFT) ||
  774.                                    constraints.equals(JSplitPane.TOP))) {
  775.             toRemove = getLeftComponent();
  776.             if (toRemove != null) {
  777.                 remove(toRemove);
  778.             }
  779.             leftComponent = comp;
  780.             index = -1;
  781.         } else if (constraints != null &&
  782.                    (constraints.equals(JSplitPane.RIGHT) ||
  783.                     constraints.equals(JSplitPane.BOTTOM))) {
  784.             toRemove = getRightComponent();
  785.             if (toRemove != null) {
  786.                 remove(toRemove);
  787.             }
  788.             rightComponent = comp;
  789.             index = -1;
  790.         } else if (constraints != null &&
  791.                 constraints.equals(JSplitPane.DIVIDER)) {
  792.             index = -1;
  793.         }
  794.         /* LayoutManager should raise for else condition here. */
  795.  
  796.         super.addImpl(comp, constraints, index);
  797.  
  798.         // Update the JSplitPane on the screen
  799.         revalidate();
  800.         repaint();
  801.     }
  802.  
  803.     /**
  804.      * Subclassed to message the UI with finishedPaintingChildren after
  805.      * super has been messaged, as well as painting the border.
  806.      *
  807.      * @param g the Graphics context within which to paint
  808.      */
  809.     protected void paintChildren(Graphics g) {
  810.         super.paintChildren(g);
  811.  
  812.         SplitPaneUI        ui = getUI();
  813.  
  814.         if (ui != null) {
  815.             Graphics           tempG = SwingGraphics.createSwingGraphics(g);
  816.             ui.finishedPaintingChildren(this, tempG);
  817.             tempG.dispose();
  818.         }
  819.     }
  820.  
  821.     /** 
  822.      * See readObject() and writeObject() in JComponent for more 
  823.      * information about serialization in Swing.
  824.      */
  825.     private void writeObject(ObjectOutputStream s) throws IOException {
  826.         s.defaultWriteObject();
  827.         if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  828.             ui.installUI(this);
  829.         }
  830.     }
  831.  
  832.  
  833.     /**
  834.      * Returns a string representation of this JSplitPane. This method 
  835.      * is intended to be used only for debugging purposes, and the 
  836.      * content and format of the returned string may vary between      
  837.      * implementations. The returned string may be empty but may not 
  838.      * be <code>null</code>.
  839.      * <P>
  840.      * Overriding paramString() to provide information about the
  841.      * specific new aspects of the JFC components.
  842.      * 
  843.      * @return  a string representation of this JSplitPane.
  844.      */
  845.     protected String paramString() {
  846.         String orientationString = (orientation == HORIZONTAL_SPLIT ?
  847.                                     "HORIZONTAL_SPLIT" : "VERTICAL_SPLIT");
  848.         String continuousLayoutString = (continuousLayout ?
  849.                                          "true" : "false");
  850.         String oneTouchExpandableString = (oneTouchExpandable ?
  851.                                            "true" : "false");
  852.  
  853.         return super.paramString() +
  854.         ",continuousLayout=" + continuousLayoutString +
  855.         ",dividerSize=" + dividerSize +
  856.         ",lastDividerLocation=" + lastDividerLocation +
  857.         ",oneTouchExpandable=" + oneTouchExpandableString +
  858.         ",orientation=" + orientationString;
  859.     }
  860.  
  861. /////////////////
  862. // Accessibility support
  863. ////////////////
  864.  
  865.     /**
  866.      * Get the AccessibleContext associated with this JComponent
  867.      *
  868.      * @return the AccessibleContext of this JComponent
  869.      * @beaninfo
  870.      *       expert: true
  871.      *  description: The AccessibleContext associated with this Label.
  872.      */
  873.     public AccessibleContext getAccessibleContext() {
  874.         if (accessibleContext == null) {
  875.             accessibleContext = new AccessibleJSplitPane();
  876.         }
  877.         return accessibleContext;
  878.     }
  879.  
  880.     /**
  881.      * The class used to obtain the accessible role for this object.
  882.      * <p>
  883.      * <strong>Warning:</strong>
  884.      * Serialized objects of this class will not be compatible with
  885.      * future Swing releases.  The current serialization support is appropriate
  886.      * for short term storage or RMI between applications running the same
  887.      * version of Swing.  A future release of Swing will provide support for
  888.      * long term persistence.
  889.      */
  890.     protected class AccessibleJSplitPane extends AccessibleJComponent 
  891.         implements AccessibleValue {
  892.  
  893.         /**
  894.          * Get the state set of this object.
  895.          *
  896.          * @return an instance of AccessibleState containing the current state 
  897.          * of the object
  898.          * @see AccessibleState
  899.          */
  900.         public AccessibleStateSet getAccessibleStateSet() {
  901.             AccessibleStateSet states = super.getAccessibleStateSet();
  902.             // FIXME: [[[WDW - Should also add BUSY if this implements
  903.             // Adjustable at some point.  If this happens, we probably
  904.             // should also add actions.]]]
  905.             if (getOrientation() == VERTICAL_SPLIT) {
  906.                 states.add(AccessibleState.VERTICAL);
  907.             } else {
  908.                 states.add(AccessibleState.HORIZONTAL);
  909.             }
  910.             return states;
  911.         }
  912.     
  913.         /**
  914.          * Get the AccessibleValue associated with this object if one
  915.          * exists.  Otherwise return null.
  916.          */
  917.         public AccessibleValue getAccessibleValue() {
  918.             return this;
  919.         }
  920.  
  921.         /**
  922.          * Get the accessible value of this object.
  923.          *
  924.          * @return a localized String describing the value of this object
  925.          */
  926.         public Number getCurrentAccessibleValue() {
  927.             return new Integer(getDividerLocation());
  928.         }
  929.     
  930.         /**
  931.          * Set the value of this object as a Number.
  932.          *
  933.          * @return True if the value was set.
  934.          */
  935.         public boolean setCurrentAccessibleValue(Number n) {
  936.             if (n instanceof Integer) {
  937.                 setDividerLocation(n.intValue());
  938.                 return true;
  939.             } else {
  940.                 return false;
  941.             }
  942.         }
  943.     
  944.         /**
  945.          * Get the minimum accessible value of this object.
  946.          *
  947.          * @return The minimum value of this object.
  948.          */
  949.         public Number getMinimumAccessibleValue() {
  950.             return new Integer(getUI().getMinimumDividerLocation(
  951.                                                         JSplitPane.this));
  952.         }
  953.     
  954.         /**
  955.          * Get the maximum accessible value of this object.
  956.          *
  957.          * @return The maximum value of this object.
  958.          */
  959.         public Number getMaximumAccessibleValue() {
  960.             return new Integer(getUI().getMaximumDividerLocation(
  961.                                                         JSplitPane.this));
  962.         }
  963.     
  964.         /**
  965.          * Get the role of this object.
  966.          *
  967.          * @return an instance of AccessibleRole describing the role of 
  968.          * the object
  969.          * @see AccessibleRole
  970.          */
  971.         public AccessibleRole getAccessibleRole() {
  972.             return AccessibleRole.SPLIT_PANE;
  973.         }
  974.     } // inner class AccessibleJSplitPane
  975. }
  976.